package de.hft_stuttgart.dsa.ctt.processing.genetic;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import de.hft_stuttgart.dsa.ctt.model.CourseAssignmentMatrix;
import de.hft_stuttgart.dsa.ctt.model.FitnessToMatrix;
import de.hft_stuttgart.dsa.ctt.model.ProblemInstance;
import de.hft_stuttgart.dsa.ctt.validation.FitnessEvaluator;

/**
 * @author Eduard Tudenhoefner
 */
public class Selector {

	/**
	 * Selection is done based on the fitness of each solution. In our case the
	 * fitness is indicated by the number of soft constraint penalties.
	 * 
	 * @param numberOfParents
	 *            Number of parents that should be selection in order to create
	 *            a new population.
	 * @param initialPopulation
	 *            The population where to select from.
	 * @return A list of parents that can be used for creating a new population.
	 */
	public List<CourseAssignmentMatrix> selectParentsForReproduction(int numberOfParents, List<CourseAssignmentMatrix> initialPopulation, ProblemInstance problemInstance) {
		List<CourseAssignmentMatrix> parentsForReproduction = new ArrayList<CourseAssignmentMatrix>();
		List<FitnessToMatrix> fitnessToMatrixValues = new ArrayList<FitnessToMatrix>(initialPopulation.size());

		for (CourseAssignmentMatrix matrix : initialPopulation) {
			int fitnessValue = new FitnessEvaluator(problemInstance, matrix).calculateSoftConstraintPenalty();
			fitnessToMatrixValues.add(new FitnessToMatrix(fitnessValue, matrix));
		}

		// the population is sorted based on the fitness value
		Collections.sort(fitnessToMatrixValues, new Comparator<FitnessToMatrix>() {
			@Override
			public int compare(FitnessToMatrix obj1, FitnessToMatrix obj2) {
				return obj1.compareTo(obj2);
			}
		});

		for (int i = 0; i < numberOfParents; i++) {
			parentsForReproduction.add((CourseAssignmentMatrix) fitnessToMatrixValues.get(i).getMatrix());
		}

		return parentsForReproduction;
	}
}
